//! Script# Silverlight Bootstrapper
//! Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//! http://projects.nikhilk.net
//!

if (!window.__sl) {
    window.__sl = { supported: false, os: null, version: null, activex: false, count: 0 };

    var supported = false;
    var ua = window.navigator.userAgent;
    if (ua.indexOf('Windows NT') >= 0) {
        window.__sl.os = 'Windows';
    }
    else if (ua.indexOf('PPC Mac OS X') >= 0) {
        window.__sl.os = 'MacPPC';
    }
    else if (ua.indexOf('Intel Mac OS X') >= 0) {
        window.__sl.os = 'MacIntel';
    }
    if (window.__sl.os) {
        if (ua.indexOf('MSIE') >= 0) {
            if (parseInt(ua.split('MSIE')[1]) >= 6) {
                supported = true;
                window.__sl.activex = true;
            }
        }
        else if (ua.indexOf('Firefox')) {
            var version = ua.split('Firefox/')[1].split('.');
            var major = parseInt(version[0]);
            if (major >= 2) {
                supported = true;
            }
            else {
                var minor = parseInt(version[1]);
                if ((major == 1) && (minor >= 5)) {
                    supported = true;
                }
            }
        }
        else if (ua.indexOf('Safari') >= 0) {
            supported = true;
        }
    }
    
    window.__sl.supported = supported;
    if (!supported) {
        window.__sl.version = '';
    }
}

window.__sl.getVersion = function() {
    if (window.__sl.version === null) {
        window.__sl.version == '';
        var container = null;
        try {
            var control = null;
            if (window.__sl.activex) {
                control = new ActiveXObject('AgControl.AgControl');
            }
            else {
                if (navigator.plugins['Silverlight Plug-In']) {
                    container = document.createElement('div');
                    document.body.appendChild(container);

                    container.innerHTML= '<embed type="application/x-silverlight" src="data:," />';
                    control = container.childNodes[0];
                }
            }
            if (control) {
                var versionParts = [0,0,0,0];
                for (var i = 0; i < versionParts.length; i++) {
                    for (var n = 0; n < 100000; n++) {
                        versionParts[i] = n;
                        if (!control.isVersionSupported(versionParts.join('.'))) {
                            versionParts[i] = n - 1;
                            break;
                        } 
                    }
                }
                window.__sl.version = versionParts;
            }
        }
        catch (e) {
        }
        if (container) {
            document.body.removeChild(container);
        }
    }
    return window.__sl.version;
}

window.__sl.cleanup = function() {
    for (var i = window.__sl.count - 1; i >= 0; i--) {
        window['__slonLoad' + i] = null;
        window['__slonError' + i] = null;
    }
    if (window.removeEventListener) {
        window.removeEventListener('unload', window.__sl.cleanup, false);
    }
    else {
        window.detachEvent('onunload', window.__sl.cleanup);
    }
}

function $create_ControlParameters(source, parentElement, id, className) {
    return { source: source, parentElement: parentElement, id: id, className: className };
}

function createInstallPrompt(version, parentElement, installPromptBanner, useNewWindow) {
    var fwLink = 'http://go.microsoft.com/fwlink/?LinkID=';
    var pages = {
        'Windows1.0': '92800', 'MacIntel1.0': '92812', 'MacPPC1.0': '92811',
        'Windows1.1': '92809', 'MacIntel1.1': '92813'
    };
    var images = {
        '1.0': '94377', '1.1': '94378'
    };

    var markupBuilder = [];
    markupBuilder.push('<a class="silverlightInstallPrompt" title="Click here to install Silverlight." href="');
    markupBuilder.push(fwLink);
    markupBuilder.push(pages[window.__sl.os + version]);
    markupBuilder.push('"');
    if (useNewWindow) {
        markupBuilder.push(' target="_new"');
    }
    markupBuilder.push('><img border="0" src="');
    if (installPromptBanner) {
        markupBuilder.push(installPromptBanner);
    }
    else {
        markupBuilder.push(fwLink);
        markupBuilder.push(images[version]);
    }
    markupBuilder.push('" /></a>');

    parentElement.innerHTML = markupBuilder.join('');
}

function isSilverlightSupported() {
    return window.__sl.supported;
}

function isSilverlightInstalled(version) {
    var existingVersion = window.__sl.getVersion();
    if (!existingVersion || (existingVersion.length == 0)) {
        return false;
    }
    if (!version) {
        return true;
    }

    var checkParts = version.split('.');
    for (var i = 0; i < 2; i++) {
        checkParts[i] = parseInt(checkParts[i]);
    }

    if (existingVersion[0] > checkParts[0]) {
        return true;
    }
    else if (existingVersion[0] == checkParts[0]) {
        if (existingVersion[1] >= checkParts[1]) {
            return true;
        }
    }
    return false;
}

function createSilverlight(params, loadCallback, errorCallback, context) {
    if (!isSilverlightSupported()) {
        return null;
    }
    
    var version = params.version || '1.0';
    if ((version != '1.0') && (version != '1.1')) {
        alert('The only supported Silverlight versions are 1.0 and 1.1');
        return null;
    }

    var parentElement = params.parentElement;
    if (!isSilverlightInstalled(version)) {
        if (params.alternateContent !== '') {
            createInstallPrompt(version, parentElement, params.installPromptBanner, params.installInNewWindow);
        }
        else {
            parentElement.innerHTML = params.alternateContent;
        }
        return null;
    }

    if (window.__sl.count == 0) {
        if (window.addEventListener) {
            window.addEventListener('unload', window.__sl.cleanup, false);
        }
        else {
            window.attachEvent('onunload', window.__sl.cleanup);
        }
    }
    var count = window.__sl.count++;

    if (!params.source || params.xaml) {
        var xaml = params.xaml || '<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>';
        var scriptElement = document.createElement('script');
        scriptElement.type = 'text/xaml';
        scriptElement.text = xaml;
        scriptElement.id = '__slXaml' + count;

        document.body.appendChild(scriptElement);
        params.source = '#__slXaml' + count;
        delete params.xaml;
    }
    if (params.startupArguments) {
        var initParams = [];
        for (var arg in params.startupArguments) {
            initParams.push(arg);
            initParams.push('=');
            initParams.push(params.startupArguments[arg]);
            initParams.push(',');
        }
        params.initParams = initParams.join('');
        delete params.startupArguments;
    }

    var id = params.id || '__sl' + count;
    var className = params.className || '';
    var style = params.style || '';

    params.onLoad = '__slonLoad' + count;
    params.onError = '__slonError' +  count;
    
    window[params.onLoad] = function(rootElement) {
        if (loadCallback) {
            // Silverlight doesn't report things like size information
            // correctly during the load event. Delaying this just a bit
            // using window.setTimeout allows Silverlight to compute
            // the right information...
            window.setTimeout(function() { loadCallback(parentElement.childNodes[0], context); }, 0);
        }
    };
    window[params.onError] = function(sender, e) {
        if (errorCallback) {
            errorCallback(sender, e);
        }
        else {
            var errorBuilder = [];
            errorBuilder.push('Unhandled Silverlight Error: ' + e.errorMessage);
            errorBuilder.push('Control ID: ' + id);
            errorBuilder.push('Error Code: ' + e.errorCode);
            errorBuilder.push('Error Type: ' + e.errorType);

            if (e.errorType == 'ParserError') {
                errorBuilder.push('XAML File : ' + e.xamlFile);
                errorBuilder.push('Line      : ' + e.lineNumber);
                errorBuilder.push('Position  : ' + e.charPosition);
            }
            else if (e.errorType == 'RuntimeError') {
                errorBuilder.push('Method    : ' + e.methodName);
                if (e.lineNumber) {
                    errorBuilder.push('Line      : ' + e.lineNumber);
                    errorBuilder.push('Position  : ' + e.charPosition);
                }
            }
            alert(errorBuilder.join('\n'));
        }
    };

    delete params.id;
    delete params.className;
    delete params.style;
    delete params.parentElement;
    delete params.version;
    delete params.installPromptBanner;
    delete params.installUsesNewWindow;
    delete params.alternateContent;

    var markupBuilder = [];
    if (window.__sl.activex) {
        markupBuilder.push('<object type="application/x-silverlight" id="');
        markupBuilder.push(id);
        markupBuilder.push('" class="');
        markupBuilder.push(className);
        markupBuilder.push('" style="');
        markupBuilder.push(style);
        markupBuilder.push('">');
        for (var name in params) {
            markupBuilder.push('<param name="');
            markupBuilder.push(name);
            markupBuilder.push('" value="');
            markupBuilder.push(params[name]);
            markupBuilder.push('" />');
        }
        markupBuilder.push('</object>');
    }
    else {
        markupBuilder.push('<embed type="application/x-silverlight" src="data:," id="');
        markupBuilder.push(id);
        markupBuilder.push('" class="');
        markupBuilder.push(params.className);
        markupBuilder.push('" style="');
        markupBuilder.push(style);
        markupBuilder.push('"');
        for (var name in params) {
            markupBuilder.push(' ');
            markupBuilder.push(name);
            markupBuilder.push('="');
            markupBuilder.push(params[name]);
            markupBuilder.push('"');
        }
        markupBuilder.push(' />');
    }

    parentElement.innerHTML = markupBuilder.join('');
    params = null;
    markupBuilder = null;

    return parentElement.childNodes[0];
}

// Factory APIs
//

function __createFromXaml(context, name, tagName, attrs, innerContent, nameScoped) {
    var xamlBuilder = [];
    xamlBuilder.push('<');
    xamlBuilder.push(tagName);
    xamlBuilder.push(' xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"');
    if (name) {
        xamlBuilder.push(' x:Name="');
        xamlBuilder.push(name);
        xamlBuilder.push('"');
    }
    if (attrs && attrs.length) {
        for (var i = 0; i < attrs.length; i += 2) {
            xamlBuilder.push(' ');
            xamlBuilder.push(attrs[i]);
            xamlBuilder.push('="');
            xamlBuilder.push(attrs[i + 1]);
            xamlBuilder.push('"');
        }
    }
    if (!innerContent) {
        xamlBuilder.push('/>');
    }
    else {
        xamlBuilder.push('>');
        xamlBuilder.push(innerContent);
        xamlBuilder.push('</');
        xamlBuilder.push(tagName);
        xamlBuilder.push('>');
    }

    nameScoped = nameScoped ? true : false;
    return context.getHost().content.createFromXaml(xamlBuilder.join(''), nameScoped);
}

function createCanvas(context, name, nameScoped) {
    var attrs = Array.prototype.slice.call(arguments, 3);
    return __createFromXaml(context, name, 'Canvas', attrs, null, nameScoped);
}

function createStoryboard(context, name, targetName, targetProperty) {
    var attrs = Array.prototype.slice.call(arguments, 4);
    if (targetName) {
        attrs.push('Storyboard.TargetName', targetName,
                   'Storyboard.TargetProperty', targetProperty);
    }
    return __createFromXaml(context, name, 'Storyboard', attrs, null, false);
}

function createShape(context, shape, name) {
    var attrs = Array.prototype.slice.call(arguments, 3);
    return __createFromXaml(context, name, shape, attrs, null, false);
}

function createTransform(context, transform, name) {
    var attrs = Array.prototype.slice.call(arguments, 3);
    return __createFromXaml(context, name, transform, attrs, null, false);
}

function createBrush(context, brush, name) {
    var attrs = Array.prototype.slice.call(arguments, 3);
    return __createFromXaml(context, name, brush + 'Brush', attrs, null, false);
}
